/*
 * @Author: jingfuu@163.com
 * @Date: 2024-09-22 13:26:46
 * @LastEditTime: 2024-12-12 16:47:13
 * @Description: file content
 */
import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Logger,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { LogOptions } from '../decorator/log';
import BusinessType from '../enum/BusinessType';
import LoggerService from 'src/system/service/LoggerService';
import SysOperLogDto from 'src/system/dto/SysOperLogDto';
import { Util } from '../Util';
import IpUtils from '../IpUtils';
import { ClsService } from 'nestjs-cls';
import { UserSession } from '../UserSession';
import { Constants } from '../Constants';
import SystemConfigService from 'src/system/service/SystemConfigService';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  private readonly logger = new Logger(LoggingInterceptor.name);
  constructor(
    private reflector: Reflector,
    private loggerService: LoggerService,
    private cls: ClsService,
    private systemConfigService: SystemConfigService,
  ) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    // 获取 @Log 装饰器中的选项
    const logOptions = this.reflector.get<LogOptions>(
      'logOptions',
      context.getHandler(),
    );
    if (!logOptions) {
      return next.handle();
    }

    const { method, url, body, query, params } = request;
    const operLogDto = new SysOperLogDto();
    operLogDto.title = logOptions?.title || '未命名';
    operLogDto.businessType = logOptions?.businessType || BusinessType.OTHER;
    operLogDto.operTime = Util.getCurrentLocalTime();
    operLogDto.operIp = IpUtils.getIpAddr(request);
    operLogDto.operUrl = `${url}`;
    operLogDto.operParam = JSON.stringify({
      body,
      query,
      params,
    });
    operLogDto.requestMethod = method;
    const userSession = this.cls.get<UserSession>(Constants.USER_SESSION);
    if (userSession) {
      operLogDto.deptName = userSession.user.dept.deptName;
      operLogDto.operName = userSession.user.userName;
    } else {
      operLogDto.operName = '未登录';
    }
    operLogDto.method =
      context.getClass().name + '.' + context.getHandler().name;
    const start: number = performance.now();
    return next.handle().pipe(
      tap(async (data) => {
        if (await this.systemConfigService.getUserOpenOperinforFlag()) {
          operLogDto.jsonResult = JSON.stringify(data); // 记录响应内容
          const end: number = performance.now();
          operLogDto.costTime = Math.round(end - start);
          await this.loggerService.logRequest(operLogDto);
        }
      }),
    );
  }
}
